package com.nulldev.util.crypto;

import java.io.File;

import com.nulldev.util.FinalBypass;
import com.nulldev.util.crypto.api2.EncryptionUtil;
import com.nulldev.util.crypto.api2.EncryptionUtil.Types;
import com.nulldev.util.io.FileUtil;
import com.nulldev.util.io.MD5Utils;
import com.nulldev.util.io.FileUtil.ReadFileBufferCallback;
import com.nulldev.util.io.FileUtil.ReadFileBufferState;
import com.nulldev.util.logging.Logger;
import com.nulldev.util.logging.LoggerFactory;
import com.nulldev.util.math.lNumber;
import com.nulldev.util.other.ByteUtils;

@Deprecated
public class FileEncryptor {
	
	private static final Logger log = LoggerFactory.getLogger();
	
	/*
	 * ENCP format:
	 * <encp[v1]>
	 * <keyhash=<>>
	 * *data*
	 */

	public static void encryptFile(final File input, final String password) {
		final FinalBypass<Boolean> finished = new FinalBypass<Boolean>(false);
		final FinalBypass<lNumber> _bytesRead = new FinalBypass<lNumber>(lNumber.nil());
		final File out = FileUtil.safeCreate(input.toString() + ".encp");
		
		if (!out.exists()) {
			try {
				out.createNewFile();
			} catch (Exception e) {
				log.error("encryptFile(file) -> Failed to create encryted file.", e);
				return;
			}
		}
		
		try {
			FileUtil.writeFile(out, "<encp[v1]>", true);
			FileUtil.append(out, "<keyhash=" + MD5Utils.getMD5Hex(password) + ">", true);
		}catch (Exception e) {
			log.error("encryptFile(file) -> Failed to write headers.");
			return;
		}
		
		final ReadFileBufferCallback callback = new ReadFileBufferCallback() {
			
			@Override
			public void read(final byte[] data, ReadFileBufferState state, final lNumber bytesRead) {
				_bytesRead.setObject(bytesRead);
				if (state == ReadFileBufferState.ERROR || state == ReadFileBufferState.FAILED) {
					finished.setObject(true);
					log.error("encryptFile(file) -> Failed to read file.");
					return;
				}
				if (state == ReadFileBufferState.FINISHED) {
					finished.setObject(true);
					log.info("encryptFile(file) -> Finished.");
					return;
				}
				if (data == null) {
					return;
				}
				if (state != ReadFileBufferState.OK) {
					return;
				}
				final String readable = ByteUtils.toHEX(data);
				final String enc = EncryptionUtil.byType(Types.P2PE_COMPRESS).encrypt(readable, password);
				try {
					FileUtil.append(out, enc, false);
				} catch (Exception e) {
					log.error("encryptFile(file) -> Encryption failed!", e);
					try {
						out.delete();
					}catch (Exception xe) {}
					return;
				}
			}
		};
		FileUtil.readFileBuffer(input, callback);
	}
}
